package com.express.gateway;

import com.express.gateway.cluster.ClusterManagerFactory;
import com.express.gateway.common.CommonCons;
import com.express.gateway.common.util.PathUtil;
import io.netty.util.internal.logging.InternalLoggerFactory;
import io.netty.util.internal.logging.Log4J2LoggerFactory;
import io.vertx.core.VertxOptions;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.dns.AddressResolverOptions;
import io.vertx.core.eventbus.EventBusOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.core.metrics.MetricsOptions;
import io.vertx.core.spi.cluster.ClusterManager;

import java.time.LocalTime;
import java.util.UUID;

/**
 * Exp-Inlet的启动器
 *
 * @author flower
 */
public class Launcher extends io.vertx.core.Launcher {

    /**
     * 启动Exp-Inlet-Gateway
     */
    public static void start() {
        Launcher.main(new String[]{"run", "com.express.gateway.MasterVerticle"});
    }

    /**
     * 停止Exp-Inlet-Gateway
     */
    public static void stop() {
        executeCommand("stop", System.getProperty(CommonCons.KEY_VERTX));
    }

    public static void main(String[] args) {
        // 设置当前系统Vertx的唯一标识
        String vertxId = UUID.randomUUID().toString() + LocalTime.now().getNano();
        System.setProperty(CommonCons.KEY_VERTX, vertxId);
        InternalLoggerFactory.setDefaultFactory(Log4J2LoggerFactory.INSTANCE);
        System.setProperty("vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.Log4j2LogDelegateFactory");
        System.setProperty("vertx.disableDnsResolver", "true");
        new Launcher().dispatch(args);
    }

    public static void executeCommand(String cmd, String... args) {
        new Launcher().execute(cmd, args);
    }

    /**
     * 设置vert.x配置
     */
    @Override
    public void beforeStartingVertx(VertxOptions options) {
        // byte[] bytes = Files.readAllBytes(PathUtil.getPath("conf.json"));
        Buffer buff = Buffer.buffer(PathUtil.getFileContentString("conf.json"));
        // 总配置文件
        JsonObject conf = buff.toJsonObject();
        // vert.x配置文件
        JsonObject vertxCfg = conf.getJsonObject("vertx", getDefaultVertxConfig());
        initVertxConfig(vertxCfg, options);
        // 集群配置文件
        String CLUSTER_TYPE = "NONE";
        JsonObject clusterCfg = conf.getJsonObject("cluster", new JsonObject().put("clusterType", CLUSTER_TYPE));
        if (!CLUSTER_TYPE.equals(clusterCfg.getString("clusterType"))) {
            ClusterManager manager = ClusterManagerFactory.getClusterManager(clusterCfg.getString("clusterType"),
                    clusterCfg.getJsonObject("clusterConf", getDefaultClusterConfig()));
            options.setClusterManager(manager);
        }
    }

    /**
     * 初始化vert.x的配置文件<br>
     * This method copy from the {@link io.vertx.core.VertxOptionsConverter}
     * fromJson
     *
     * @param json
     * @param obj
     */
    public void initVertxConfig(JsonObject json, VertxOptions obj) {

        if (json.getValue("addressResolverOptions") instanceof JsonObject) {
            obj.setAddressResolverOptions(new AddressResolverOptions((JsonObject) json.getValue("addressResolverOptions")));
        }
        if (json.getValue("blockedThreadCheckInterval") instanceof Number) {
            obj.setBlockedThreadCheckInterval(((Number) json.getValue("blockedThreadCheckInterval")).longValue());
        }

        if (json.getValue("eventBusOptions") instanceof JsonObject) {
            obj.setEventBusOptions(new EventBusOptions((JsonObject) json.getValue("eventBusOptions")));
        }
        if (json.getValue("eventLoopPoolSize") instanceof Number) {
            obj.setEventLoopPoolSize(((Number) json.getValue("eventLoopPoolSize")).intValue());
        }
        if (json.getValue("haEnabled") instanceof Boolean) {
            obj.setHAEnabled((Boolean) json.getValue("haEnabled"));
        }
        if (json.getValue("haGroup") instanceof String) {
            obj.setHAGroup((String) json.getValue("haGroup"));
        }
        if (json.getValue("internalBlockingPoolSize") instanceof Number) {
            obj.setInternalBlockingPoolSize(((Number) json.getValue("internalBlockingPoolSize")).intValue());
        }
        if (json.getValue("maxEventLoopExecuteTime") instanceof Number) {
            obj.setMaxEventLoopExecuteTime(((Number) json.getValue("maxEventLoopExecuteTime")).longValue());
        }
        if (json.getValue("maxWorkerExecuteTime") instanceof Number) {
            obj.setMaxWorkerExecuteTime(((Number) json.getValue("maxWorkerExecuteTime")).longValue());
        }
        if (json.getValue("metricsOptions") instanceof JsonObject) {
            obj.setMetricsOptions(new MetricsOptions((JsonObject) json.getValue("metricsOptions")));
        }
        if (json.getValue("preferNativeTransport") instanceof Boolean) {
            obj.setPreferNativeTransport((Boolean) json.getValue("preferNativeTransport"));
        }
        if (json.getValue("quorumSize") instanceof Number) {
            obj.setQuorumSize(((Number) json.getValue("quorumSize")).intValue());
        }
        if (json.getValue("warningExceptionTime") instanceof Number) {
            obj.setWarningExceptionTime(((Number) json.getValue("warningExceptionTime")).longValue());
        }
        if (json.getValue("workerPoolSize") instanceof Number) {
            obj.setWorkerPoolSize(((Number) json.getValue("workerPoolSize")).intValue());
        }

    }

    /**
     * 获得默认的vert.x配置信息
     *
     * @return
     */
    public JsonObject getDefaultVertxConfig() {
        return new JsonObject().put("preferNativeTransport", true);
    }

    /**
     * 获得默认的集群配置文件
     *
     * @return
     */
    public JsonObject getDefaultClusterConfig() {
        JsonObject json = new JsonObject();
        json.put("zookeeperHosts", "127.0.0.1");
        json.put("sessionTimeout", 20000);
        json.put("connectTimeout", 3000);
        json.put("rootPath", "io.vertx");
        json.put("expApiConfPath", "/io.vertx/exp.api.gateway/conf");
        JsonObject retry = new JsonObject();
        retry.put("initialSleepTime", 100);
        retry.put("intervalTimes", 10000);
        retry.put("maxTimes", 5);
        json.put("retry", retry);
        return json;
    }

    /**
     * 获得默认的数据库配置
     *
     * @return
     */
    public JsonObject getDefaultDataConfig() {
        return new JsonObject().put("url", "jdbc:sqlite:configDB.db").put("driver_class", "org.sqlite.JDBC");
    }

    /**
     * 获得默认的客户端配置
     *
     * @return
     */
    public JsonObject getDefaultClientConfig() {
        return new JsonObject().put("clientPort", 5256);
    }

}
